package org.qtmo.emu.nes;
import flash.Vector;

/**
 * ...
 * @author Sang Hua Cai
 */

class CPU
{
	public function new(nes:NES)
	{
		this.nes = nes;

		R = new R6502();

		OpcodeMap = new Vector < Void -> Void > (0x100);

		var op:Array<Int> =
		[
		7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0,
		2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
		6, 2, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0,
		2, 2, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
		6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0,
		2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
		6, 6, 0, 0, 0, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0,
		2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
		0, 6, 0, 0, 3, 3, 3, 0, 2, 0, 2, 0, 4, 4, 4, 0,
		2, 6, 0, 0, 4, 4, 4, 0, 2, 5, 2, 0, 0, 5, 0, 0,
		2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0,
		2, 5, 0, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0,
		2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
		2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
		2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
		2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0];

		for (i in 0...op.length)
		{
			if (op[i] != 0)
			{
				OpcodeMap[i] = (Reflect.field(this, "EXEC_0x" + StringTools.hex(i, 2)));
			}
			else
			{
				OpcodeMap[i] = null;
			}
		}

		Reset();
	}

	/********************************
	 *********** 公共函数 ***********
	 ********************************/

	public function Reset():Void
	{
		/*
		mapper = nes->mapper;
		*/
		//R.Reset();
		R.PC = RD6502(RES_VECTOR);
		R.A = 0x00;
		R.P = Z_FLAG|R_FLAG;
		R.X = 0x00;
		R.Y = 0x00;
		R.S = 0xFF + MMU.STACK_OFFSET;
		R.INT_pending = 0;

		TOTAL_cycles = 0;
		DMA_cycles = 0;

		// Zero/Negative FLAG
		MMU.Write(MMU.ZN_TABLE_OFFSET, Z_FLAG);
		for (i in 1...0x100)
		{
			MMU.Write(MMU.ZN_TABLE_OFFSET + i, ((i & 0x80) > 0)?N_FLAG:0);
		}
	}

	/*
	public function GetDmaCycles():Int
	{
		return	DMA_cycles;
	}

	public function SetDmaCycles( cycles:Int ):Void
	{
		DMA_cycles = cycles;
	}

	public function GetTotalCycles():Int
	{
		return	TOTAL_cycles;
	}

	public function SetTotalCycles( cycles:Int ):Void
	{
		TOTAL_cycles = cycles;
	}

	public function DMA( cycles:Int )
	{
		DMA_cycles += cycles;
	}
	*/
	public function NMI()
	{
		R.INT_pending |= NMI_FLAG;
	}

	public function SetIRQ( mask:UInt )
	{
		R.INT_pending |= mask;
	}

	public function ClrIRQ( mask:UInt )
	{
		R.INT_pending &= ~mask;
	}

	public function EXEC( request_cycles:Int ):Int
	{
		var opcode:Int;
		var old_cycles:Int = TOTAL_cycles;
		var nmi_request:Int = 0;
		var irq_request:Int = 0;
		var bClockProcess:Bool = false;
		var m_bClockProcess:Bool = false;

		while ( request_cycles > 0 )
		{
			EXEC_cycles = 0;

			if ( DMA_cycles > 0 )
			{
				if ( request_cycles <= DMA_cycles )
				{
					DMA_cycles -= request_cycles;
					TOTAL_cycles += request_cycles;

					//TO-DO
					//mapper->Clock( request_cycles );

					if ( bClockProcess )
					{
						//TO-DO
						//nes->Clock( request_cycles );
					}
					break;
				}
				else
				{
					EXEC_cycles += DMA_cycles;
					DMA_cycles = 0;
				}
			}

			nmi_request = irq_request = 0;
			opcode = OP6502( R.PC++ );
			trace("OP::" + opcode);
			trace("PC::" + R.PC);
			trace("cycles::" + request_cycles);
			if ( R.INT_pending > 0 )
			{
				if ( (R.INT_pending & NMI_FLAG) > 0 )
				{
					nmi_request = 0xFF;
					R.INT_pending &= ~NMI_FLAG;
				}
				else if ( (R.INT_pending & (IRQ_MASK() ? 1 : 0)) > 0 )
				{
					R.INT_pending &= ~IRQ_TRIGGER2;
					if ( !(R.P & I_FLAG > 0) && opcode != 0x40 )
					{
						irq_request = 0xFF;
						R.INT_pending &= ~IRQ_TRIGGER;
					}
				}
			}

			OpcodeMap[opcode]();

			if ( nmi_request > 0)
			{
				_NMI();
			}
			else if ( irq_request > 0)
			{
				_IRQ();
			}

			request_cycles -= EXEC_cycles;
			TOTAL_cycles += EXEC_cycles;

			//TO-DO
			//mapper->Clock( EXEC_cycles );

			if ( bClockProcess )
			{
				//TO-DO
				//nes->Clock( EXEC_cycles );
			}
		}

		//TO-DO
		//nes.apu->SyncDPCM( TOTAL_cycles - old_cycles );
		return	TOTAL_cycles - old_cycles;
	}

	/********************************
	 ************ 指令集 ************
	 ********************************/

	private function EXEC_0x69():Void
	{ // ADC #$??
		MR_IM();
		ADC();
		ADD_CYCLE(2);
	}
	private function EXEC_0x65():Void
	{ // ADC $??
		MR_ZP();
		ADC();
		ADD_CYCLE(3);
	}
	private function EXEC_0x75():Void
	{ // ADC $??,X
		MR_ZX(); ADC();
		ADD_CYCLE(4);
	}
	private function EXEC_0x6D():Void
	{ // ADC $????
		MR_AB(); ADC();
		ADD_CYCLE(4);
	}
	private function EXEC_0x7D():Void
	{ // ADC $????,X
		MR_AX(); ADC(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x79():Void
	{ // ADC $????,Y
		MR_AY(); ADC(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x61():Void
	{ // ADC ($??,X)
		MR_IX(); ADC();
		ADD_CYCLE(6);
	}
	private function EXEC_0x71():Void
	{ // ADC ($??),Y
		MR_IY(); ADC(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xE9():Void
	{ // SBC #$??
		MR_IM(); SBC();
		ADD_CYCLE(2);
	}
	private function EXEC_0xE5():Void
	{ // SBC $??
		MR_ZP(); SBC();
		ADD_CYCLE(3);
	}
	private function EXEC_0xF5():Void
	{ // SBC $??,X
		MR_ZX(); SBC();
		ADD_CYCLE(4);
	}
	private function EXEC_0xED():Void
	{ // SBC $????
		MR_AB(); SBC();
		ADD_CYCLE(4);
	}
	private function EXEC_0xFD():Void
	{ // SBC $????,X
		MR_AX(); SBC(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xF9():Void
	{ // SBC $????,Y
		MR_AY(); SBC(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xE1():Void
	{ // SBC ($??,X)
		MR_IX(); SBC();
		ADD_CYCLE(6);
	}
	private function EXEC_0xF1():Void
	{ // SBC ($??),Y
		MR_IY(); SBC(); CHECK_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0xC6():Void
	{ // DEC $??
		MR_ZP(); DEC();	MW_ZP();
		ADD_CYCLE(5);
	}
	private function EXEC_0xD6():Void
	{ // DEC $??,X
		MR_ZX(); DEC(); MW_ZP();
		ADD_CYCLE(6);
	}
	private function EXEC_0xCE():Void
	{ // DEC $????
		MR_AB(); DEC(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0xDE():Void
	{ // DEC $????,X
		MR_AX(); DEC(); MW_EA();
		ADD_CYCLE(7);
	}
	private function EXEC_0xCA():Void
	{ // DEX
		DEX();
		ADD_CYCLE(2);
	}
	private function EXEC_0x88():Void
	{ // DEY
		DEY();
		ADD_CYCLE(2);
	}
	private function EXEC_0xE6():Void
	{ // INC $??
		MR_ZP(); INC(); MW_ZP();
		ADD_CYCLE(5);
	}
	private function EXEC_0xF6():Void
	{ // INC $??,X
		MR_ZX(); INC(); MW_ZP();
		ADD_CYCLE(6);
	}
	private function EXEC_0xEE():Void
	{ // INC $????
		MR_AB(); INC(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0xFE():Void
	{ // INC $????,X
		MR_AX(); INC(); MW_EA();
		ADD_CYCLE(7);
	}
	private function EXEC_0xE8():Void
	{ // INX
		INX();
		ADD_CYCLE(2);
	}
	private function EXEC_0xC8():Void
	{ // INY
		INY();
		ADD_CYCLE(2);
	}
	private function EXEC_0x29():Void
	{ // AND #$??
		MR_IM(); AND();
		ADD_CYCLE(2);
	}
	private function EXEC_0x25():Void
	{ // AND $??
		MR_ZP(); AND();
		ADD_CYCLE(3);
	}
	private function EXEC_0x35():Void
	{ // AND $??,X
		MR_ZX(); AND();
		ADD_CYCLE(4);
	}
	private function EXEC_0x2D():Void
	{// AND $????
		MR_AB(); AND();
		ADD_CYCLE(4);
	}
	private function EXEC_0x3D():Void
	{ // AND $????,X
		MR_AX(); AND(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x39():Void
	{ // AND $????,Y
		MR_AY(); AND(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x21():Void
	{ // AND ($??,X)
		MR_IX(); AND();
		ADD_CYCLE(6);
	}
	private function EXEC_0x31():Void
	{ // AND ($??),Y
		MR_IY(); AND(); CHECK_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0x0A():Void
	{ // ASL A
		ASL_A();
		ADD_CYCLE(2);
	}
	private function EXEC_0x06():Void
	{ // ASL $??
		MR_ZP(); ASL(); MW_ZP();
		ADD_CYCLE(5);
	}
	private function EXEC_0x16():Void
	{ // ASL $??,X
		MR_ZX(); ASL(); MW_ZP();
		ADD_CYCLE(6);
	}
	private function EXEC_0x0E():Void
	{ // ASL $????
		MR_AB(); ASL(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x1E():Void
	{ // ASL $????,X
		MR_AX(); ASL(); MW_EA();
		ADD_CYCLE(7);
	}
	private function EXEC_0x24():Void
	{ // BIT $??
		MR_ZP(); BIT();
		ADD_CYCLE(3);
	}
	private function EXEC_0x2C():Void
	{ // BIT $????
		MR_AB(); BIT();
		ADD_CYCLE(4);
	}
	private function EXEC_0x49():Void
	{ // EOR #$??
		MR_IM(); EOR();
		ADD_CYCLE(2);
	}
	private function EXEC_0x45():Void
	{ // EOR $??
		MR_ZP(); EOR();
		ADD_CYCLE(3);
	}
	private function EXEC_0x55():Void
	{ // EOR $??,X
		MR_ZX(); EOR();
		ADD_CYCLE(4);
	}
	private function EXEC_0x4D():Void
	{ // EOR $????
		MR_AB(); EOR();
		ADD_CYCLE(4);
	}
	private function EXEC_0x5D():Void
	{ // EOR $????,X
		MR_AX(); EOR(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x59():Void
	{ // EOR $????,Y
		MR_AY(); EOR(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x41():Void
	{ // EOR ($??,X)
		MR_IX(); EOR();
		ADD_CYCLE(6);
	}
	private function EXEC_0x51():Void
	{ // EOR ($??),Y
		MR_IY(); EOR(); CHECK_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0x4A():Void
	{ // LSR A
		LSR_A();
		ADD_CYCLE(2);
	}
	private function EXEC_0x46():Void
	{ // LSR $??
		MR_ZP(); LSR(); MW_ZP();
		ADD_CYCLE(5);
	}
	private function EXEC_0x56():Void
	{ // LSR $??,X
		MR_ZX(); LSR(); MW_ZP();
		ADD_CYCLE(6);
	}
	private function EXEC_0x4E():Void
	{ // LSR $????
		MR_AB(); LSR(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x5E():Void
	{ // LSR $????,X
		MR_AX(); LSR(); MW_EA();
		ADD_CYCLE(7);
	}
	private function EXEC_0x09():Void
	{ // ORA #$??
		MR_IM(); ORA();
		ADD_CYCLE(2);
	}
	private function EXEC_0x05():Void
	{ // ORA $??
		MR_ZP(); ORA();
		ADD_CYCLE(3);
	}
	private function EXEC_0x15():Void
	{ // ORA $??,X
		MR_ZX(); ORA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x0D():Void
	{ // ORA $????
		MR_AB(); ORA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x1D():Void
	{ // ORA $????,X
		MR_AX(); ORA(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x19():Void
	{ // ORA $????,Y
		MR_AY(); ORA(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x01():Void
	{ // ORA ($??,X)
		MR_IX(); ORA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x11():Void
	{ // ORA ($??),Y
		MR_IY(); ORA(); CHECK_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0x2A():Void
	{ // ROL A
		ROL_A();
		ADD_CYCLE(2);
	}
	private function EXEC_0x26():Void
	{ // ROL $??
		MR_ZP(); ROL(); MW_ZP();
		ADD_CYCLE(5);
	}
	private function EXEC_0x36():Void
	{ // ROL $??,X
		MR_ZX(); ROL(); MW_ZP();
		ADD_CYCLE(6);
	}
	private function EXEC_0x2E():Void
	{ // ROL $????
		MR_AB(); ROL(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x3E():Void
	{ // ROL $????,X
		MR_AX(); ROL(); MW_EA();
		ADD_CYCLE(7);
	}
	private function EXEC_0x6A():Void
	{ // ROR A
		ROR_A();
		ADD_CYCLE(2);
	}
	private function EXEC_0x66():Void
	{ // ROR $??
		MR_ZP(); ROR(); MW_ZP();
		ADD_CYCLE(5);
	}
	private function EXEC_0x76():Void
	{ // ROR $??,X
		MR_ZX(); ROR(); MW_ZP();
		ADD_CYCLE(6);
	}
	private function EXEC_0x6E():Void
	{ // ROR $????
		MR_AB(); ROR(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x7E():Void
	{ // ROR $????,X
		MR_AX(); ROR(); MW_EA();
		ADD_CYCLE(7);
	}
	private function EXEC_0xA9():Void
	{ // LDA #$??
		MR_IM(); LDA();
		ADD_CYCLE(2);
	}
	private function EXEC_0xA5():Void
	{ // LDA $??
		MR_ZP(); LDA();
		ADD_CYCLE(3);
	}
	private function EXEC_0xB5():Void
	{ // LDA $??,X
		MR_ZX(); LDA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xAD():Void
	{ // LDA $????
		MR_AB(); LDA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xBD():Void
	{ // LDA $????,X
		MR_AX(); LDA(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xB9():Void
	{ // LDA $????,Y
		MR_AY(); LDA(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xA1():Void
	{ // LDA ($??,X)
		MR_IX(); LDA();
		ADD_CYCLE(6);
	}
	private function EXEC_0xB1():Void
	{ // LDA ($??),Y
		MR_IY(); LDA(); CHECK_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0xA2():Void
	{ // LDX #$??
		MR_IM(); LDX();
		ADD_CYCLE(2);
	}
	private function EXEC_0xA6():Void
	{ // LDX $??
		MR_ZP(); LDX();
		ADD_CYCLE(3);
	}
	private function EXEC_0xB6():Void
	{ // LDX $??,Y
		MR_ZY(); LDX();
		ADD_CYCLE(4);
	}
	private function EXEC_0xAE():Void
	{ // LDX $????
		MR_AB(); LDX();
		ADD_CYCLE(4);
	}
	private function EXEC_0xBE():Void
	{ // LDX $????,Y
		MR_AY(); LDX(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xA0():Void
	{ // LDY #$??
		MR_IM(); LDY();
		ADD_CYCLE(2);
	}
	private function EXEC_0xA4():Void
	{ // LDY $??
		MR_ZP(); LDY();
		ADD_CYCLE(3);
	}
	private function EXEC_0xB4():Void
	{ // LDY $??,X
		MR_ZX(); LDY();
		ADD_CYCLE(4);
	}
	private function EXEC_0xAC():Void
	{ // LDY $????
		MR_AB(); LDY();
		ADD_CYCLE(4);
	}
	private function EXEC_0xBC():Void
	{ // LDY $????,X
		MR_AX(); LDY(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x85():Void
	{ // STA $??
		EA_ZP(); STA(); MW_ZP();
		ADD_CYCLE(3);
	}
	private function EXEC_0x95():Void
	{ // STA $??,X
		EA_ZX(); STA(); MW_ZP();
		ADD_CYCLE(4);
	}
	private function EXEC_0x8D():Void
	{ // STA $????
		EA_AB(); STA(); MW_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x9D():Void
	{ // STA $????,X
		EA_AX(); STA(); MW_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0x99():Void
	{ // STA $????,Y
		EA_AY(); STA(); MW_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0x81():Void
	{ // STA ($??,X)
		EA_IX(); STA(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x91():Void
	{ // STA ($??),Y
		EA_IY(); STA(); MW_EA();
		ADD_CYCLE(6);
	}
	private function EXEC_0x86():Void
	{ // STX $??
		EA_ZP(); STX(); MW_ZP();
		ADD_CYCLE(3);
	}
	private function EXEC_0x96():Void
	{ // STX $??,Y
		EA_ZY(); STX(); MW_ZP();
		ADD_CYCLE(4);
	}
	private function EXEC_0x8E():Void
	{ // STX $????
		EA_AB(); STX(); MW_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0x84():Void
	{ // STY $??
		EA_ZP(); STY(); MW_ZP();
		ADD_CYCLE(3);
	}
	private function EXEC_0x94():Void
	{ // STY $??,X
		EA_ZX(); STY(); MW_ZP();
		ADD_CYCLE(4);
	}
	private function EXEC_0x8C():Void
	{ // STY $????
		EA_AB(); STY(); MW_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xAA():Void
	{ // TAX
		TAX();
		ADD_CYCLE(2);
	}
	private function EXEC_0x8A():Void
	{ // TXA
		TXA();
		ADD_CYCLE(2);
	}
	private function EXEC_0xA8():Void
	{ // TAY
		TAY();
		ADD_CYCLE(2);
	}
	private function EXEC_0x98():Void
	{ // TYA
		TYA();
		ADD_CYCLE(2);
	}
	private function EXEC_0xBA():Void
	{ // TSX
		TSX();
		ADD_CYCLE(2);
	}
	private function EXEC_0x9A():Void
	{ // TXS
		TXS();
		ADD_CYCLE(2);
	}
	private function EXEC_0xC9():Void
	{ // CMP #$??
		MR_IM(); CMP_();
		ADD_CYCLE(2);
	}
	private function EXEC_0xC5():Void
	{ // CMP $??
		MR_ZP(); CMP_();
		ADD_CYCLE(3);
	}
	private function EXEC_0xD5():Void
	{ // CMP $??,X
		MR_ZX(); CMP_();
		ADD_CYCLE(4);
	}
	private function EXEC_0xCD():Void
	{ // CMP $????
		MR_AB(); CMP_();
		ADD_CYCLE(4);
	}
	private function EXEC_0xDD():Void
	{ // CMP $????,X
		MR_AX(); CMP_(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xD9():Void
	{ // CMP $????,Y
		MR_AY(); CMP_(); CHECK_EA();
		ADD_CYCLE(4);
	}
	private function EXEC_0xC1():Void
	{ // CMP ($??,X)
		MR_IX(); CMP_();
		ADD_CYCLE(6);
	}
	private function EXEC_0xD1():Void
	{ // CMP ($??),Y
		MR_IY(); CMP_(); CHECK_EA();
		ADD_CYCLE(5);
	}
	private function EXEC_0xE0():Void
	{ // CPX #$??
		MR_IM(); CPX();
		ADD_CYCLE(2);
	}
	private function EXEC_0xE4():Void
	{ // CPX $??
		MR_ZP(); CPX();
		ADD_CYCLE(3);
	}
	private function EXEC_0xEC():Void
	{ // CPX $????
		MR_AB(); CPX();
		ADD_CYCLE(4);
	}
	private function EXEC_0xC0():Void
	{ // CPY #$??
		MR_IM(); CPY();
		ADD_CYCLE(2);
	}
	private function EXEC_0xC4():Void
	{ // CPY $??
		MR_ZP(); CPY();
		ADD_CYCLE(3);
	}
	private function EXEC_0xCC():Void
	{ // CPY $????
		MR_AB(); CPY();
		ADD_CYCLE(4);
	}
	private function EXEC_0x90():Void
	{ // BCC
		MR_IM(); BCC();
		ADD_CYCLE(2);
	}
	private function EXEC_0xB0():Void
	{ // BCS
		MR_IM(); BCS();
		ADD_CYCLE(2);
	}
	private function EXEC_0xF0():Void
	{ // BEQ
		MR_IM(); BEQ();
		ADD_CYCLE(2);
	}
	private function EXEC_0x30():Void
	{ // BMI
		MR_IM(); BMI();
		ADD_CYCLE(2);
	}
	private function EXEC_0xD0():Void
	{ // BNE
		MR_IM(); BNE();
		ADD_CYCLE(2);
	}
	private function EXEC_0x10():Void
	{ // BPL
		MR_IM(); BPL();
		ADD_CYCLE(2);
	}
	private function EXEC_0x50():Void
	{ // BVC
		MR_IM(); BVC();
		ADD_CYCLE(2);
	}
	private function EXEC_0x70():Void
	{ // BVS
		MR_IM(); BVS();
		ADD_CYCLE(2);
	}
	private function EXEC_0x4C():Void
	{ // JMP $????
		JMP();
		ADD_CYCLE(3);
	}
	private function EXEC_0x6C():Void
	{ // JMP ($????)
		JMP_ID();
		ADD_CYCLE(5);
	}
	private function EXEC_0x20():Void
	{ // JSR
		JSR();
		ADD_CYCLE(6);
	}
	private function EXEC_0x40():Void
	{ // RTI
		RTI();
		ADD_CYCLE(6);
	}
	private function EXEC_0x60():Void
	{ // RTS
		RTS();
		ADD_CYCLE(6);
	}
	private function EXEC_0x18():Void
	{ // CLC
		CLC();
		ADD_CYCLE(2);
	}
	private function EXEC_0xD8():Void
	{ // CLD
		CLD();
		ADD_CYCLE(2);
	}
	private function EXEC_0x58():Void
	{ // CLI
		CLI();
		ADD_CYCLE(2);
	}
	private function EXEC_0xB8():Void
	{ // CLV
		CLV();
		ADD_CYCLE(2);
	}

	private function EXEC_0x38():Void
	{ // SEC
		SEC();
		ADD_CYCLE(2);
	}
	private function EXEC_0xF8():Void
	{ // SED
		SED();
		ADD_CYCLE(2);
	}
	private function EXEC_0x78():Void
	{ // SEI
		SEI();
		ADD_CYCLE(2);
	}
	private function EXEC_0x48():Void
	{ // PHA
		PUSH( R.A );
		ADD_CYCLE(3);
	}
	private function EXEC_0x08():Void
	{ // PHP
		PUSH( R.P | B_FLAG );
		ADD_CYCLE(3);
	}
	private function EXEC_0x68():Void
	{ // PLA (N-----Z-)
		R.A = POP();
		SET_ZN_FLAG(R.A);
		ADD_CYCLE(4);
	}
	private function EXEC_0x28():Void
	{ // PLP
		R.P = POP() | R_FLAG;
		ADD_CYCLE(4);
	}
	private function EXEC_0x00():Void
	{ // BRK
		BRK();
		ADD_CYCLE(7);
	}
	private function EXEC_0xEA():Void
	{ // NOP
		ADD_CYCLE(2);
	}

	/********************************
	 *********** 函数调用 ***********
	 ********************************/
	private inline function	ADC():Void
	{
		WT = R.A+DT+(R.P&C_FLAG);
		TST_FLAG( WT > 0xFF, C_FLAG );
		TST_FLAG( ((~(R.A^DT))&(R.A^WT)&0x80) > 0, V_FLAG );
		R.A = WT;
		SET_ZN_FLAG(R.A);
	}
	/* SBC (NV----ZC) */
	private inline function	SBC():Void
	{
		WT = R.A-DT-(~R.P&C_FLAG);
		TST_FLAG( ((R.A^DT) & (R.A^WT)&0x80) > 0, V_FLAG );
		TST_FLAG( WT < 0x100, C_FLAG );
		R.A = WT;
		SET_ZN_FLAG(R.A);
	}
	/* INC (N-----Z-) */
	private inline function	INC():Void
	{
		DT++;
		SET_ZN_FLAG(DT);
	}
	/* INX (N-----Z-) */
	private inline function	INX():Void
	{
		R.X++;
		SET_ZN_FLAG(R.X);
	}
	/* INY (N-----Z-) */
	private inline function	INY():Void
	{
		R.Y++;
		SET_ZN_FLAG(R.Y);
	}
	/* DEC (N-----Z-) */
	private inline function	DEC():Void
	{
		DT--;
		SET_ZN_FLAG(DT);
	}
	/* DEX (N-----Z-) */
	private inline function	DEX():Void
	{
		R.X--;
		SET_ZN_FLAG(R.X);
	}
	/* DEY (N-----Z-) */
	private inline function	DEY():Void
	{
		R.Y--;
		SET_ZN_FLAG(R.Y);
	}
	/* AND (N-----Z-) */
	private inline function	AND():Void
	{
		R.A &= DT;
		SET_ZN_FLAG(R.A);
	}
	/* ORA (N-----Z-) */
	private inline function	ORA():Void
	{
		R.A |= DT;
		SET_ZN_FLAG(R.A);
	}
	/* EOR (N-----Z-) */
	private inline function	EOR():Void
	{
		R.A ^= DT;
		SET_ZN_FLAG(R.A);
	}
	/* ASL_A (N-----ZC) */
	private inline function	ASL_A():Void
	{
		TST_FLAG( (R.A&0x80) > 0, C_FLAG );
		R.A <<= 1;
		SET_ZN_FLAG(R.A);
	}
	/* ASL (N-----ZC) */
	private inline function	ASL():Void
	{
		TST_FLAG( (DT&0x80) > 0, C_FLAG );
		DT <<= 1;
		SET_ZN_FLAG(DT);
	}
	/* LSR_A (N-----ZC) */
	private inline function	LSR_A():Void
	{
		TST_FLAG( (R.A&0x01) > 0, C_FLAG );
		R.A >>= 1;
		SET_ZN_FLAG(R.A);
	}
	/* LSR (N-----ZC) */
	private inline function	LSR():Void
	{
		TST_FLAG( (DT&0x01) > 0, C_FLAG );
		DT >>= 1;
		SET_ZN_FLAG(DT);
	}
	/* ROL_A (N-----ZC) */
	private inline function	ROL_A():Void
	{
		if( (R.P & C_FLAG) > 0 ) {
			TST_FLAG((R.A&0x80) > 0,C_FLAG);
			R.A = (R.A<<1)|0x01;
		} else {
			TST_FLAG((R.A&0x80) > 0,C_FLAG);
			R.A <<= 1;
		}
		SET_ZN_FLAG(R.A);
	}
	/* ROL (N-----ZC) */
	private inline function	ROL():Void
	{
		if( (R.P & C_FLAG) > 0 ) {
			TST_FLAG((DT&0x80) > 0,C_FLAG);
			DT = (DT<<1)|0x01;
		} else {
			TST_FLAG((DT&0x80) > 0,C_FLAG);
			DT <<= 1;
		}
		SET_ZN_FLAG(DT);
	}
	/* ROR_A (N-----ZC) */
	private inline function	ROR_A():Void
	{
		if( (R.P & C_FLAG) > 0 ) {
			TST_FLAG((R.A&0x01) > 0,C_FLAG);
			R.A = (R.A>>1)|0x80;
		} else {
			TST_FLAG((R.A&0x01) > 0,C_FLAG);
			R.A >>= 1;
		}
		SET_ZN_FLAG(R.A);
	}
	/* ROR (N-----ZC) */
	private inline function	ROR():Void
	{
		if( (R.P & C_FLAG) > 0 ) {
			TST_FLAG((DT&0x01) > 0,C_FLAG);
			DT = (DT>>1)|0x80;
		} else {
			TST_FLAG((DT&0x01) > 0,C_FLAG);
			DT >>= 1;
		}
		SET_ZN_FLAG(DT);
	}
	/* BIT (NV----Z-) */
	private inline function	BIT():Void
	{
		TST_FLAG( (DT&R.A)==0, Z_FLAG );
		TST_FLAG( (DT&0x80) > 0, N_FLAG );
		TST_FLAG( (DT&0x40) > 0, V_FLAG );
	}
	/* LDA (N-----Z-) */
	private inline function	LDA():Void
	{
		R.A = DT; SET_ZN_FLAG(R.A);
	}
	/* LDX (N-----Z-) */
	private inline function	LDX():Void
	{
		R.X = DT; SET_ZN_FLAG(R.X);
	}
	/* LDY (N-----Z-) */
	private inline function	LDY():Void
	{
		R.Y = DT; SET_ZN_FLAG(R.Y);
	}
	/* STA (--------) */
	private inline function	STA():Void
	{
		DT = R.A;
	}
	/* STX (--------) */
	private inline function	STX():Void
	{
		DT = R.X;
	}
	/* STY (--------) */
	private inline function	STY():Void
	{
		DT = R.Y;
	}
	/* TAX (N-----Z-) */
	private inline function	TAX():Void
	{
		R.X = R.A; SET_ZN_FLAG(R.X);
	}
	/* TXA (N-----Z-) */
	private inline function	TXA():Void
	{
		R.A = R.X; SET_ZN_FLAG(R.A);
	}
	/* TAY (N-----Z-) */
	private inline function	TAY():Void
	{
		R.Y = R.A; SET_ZN_FLAG(R.Y);
	}
	/* TYA (N-----Z-) */
	private inline function	TYA():Void
	{
		R.A = R.Y; SET_ZN_FLAG(R.A);
	}
	/* TSX (N-----Z-) */
	private inline function	TSX():Void
	{
		R.X = R.S; SET_ZN_FLAG(R.X);
	}
	/* TXS (--------) */
	private inline function	TXS():Void
	{
		R.S = R.X;
	}
	/* CMP (N-----ZC) */
	private inline function	CMP_():Void
	{
		WT = R.A - DT;
		TST_FLAG( (WT&0x8000)==0, C_FLAG );
		SET_ZN_FLAG( WT );
	}
	/* CPX (N-----ZC) */
	private inline function	CPX():Void
	{
		WT = R.X - DT;
		TST_FLAG( (WT&0x8000)==0, C_FLAG );
		SET_ZN_FLAG( WT );
	}
	/* CPY (N-----ZC) */
	private inline function	CPY():Void
	{
		WT = R.Y - DT;
		TST_FLAG( (WT&0x8000)==0, C_FLAG );
		SET_ZN_FLAG( WT );
	}
	private inline function	JMP_ID():Void
	{
		WT = OP6502(R.PC);
		EA = RD6502(WT);
		WT = (WT&0xFF00)|((WT+1)&0x00FF);
		R.PC = EA+RD6502(WT)*0x100;
	}
	private inline function	JMP():Void
	{
		R.PC = OP6502( R.PC );
	}
	private inline function	JSR():Void
	{
		EA = OP6502( R.PC );
		R.PC++;
		PUSH( R.PC>>8 );
		PUSH( R.PC&0xFF );
		R.PC = EA;
	}
	private inline function	RTS():Void
	{
		R.PC  = POP();
		R.PC |= POP()*0x0100;
		R.PC++;
	}
	private inline function	RTI():Void
	{
		R.P   = POP() | R_FLAG;
		R.PC  = POP();
		R.PC |= POP()*0x0100;
	}
	private inline function	_NMI():Void
	{
		PUSH( R.PC>>8 );
		PUSH( R.PC&0xFF );
		CLR_FLAG( B_FLAG );
		PUSH( R.P );
		SET_FLAG( I_FLAG );
		R.PC = RD6502(NMI_VECTOR);
		EXEC_cycles += 7;
	}
	private inline function	_IRQ():Void
	{
		PUSH( R.PC>>8 );
		PUSH( R.PC&0xFF );
		CLR_FLAG( B_FLAG );
		PUSH( R.P );
		SET_FLAG( I_FLAG );
		R.PC = RD6502(IRQ_VECTOR);
		EXEC_cycles += 7;
	}
	private inline function	BRK():Void
	{
		R.PC++;
		PUSH( R.PC>>8 );
		PUSH( R.PC&0xFF );
		SET_FLAG( B_FLAG );
		PUSH( R.P );
		SET_FLAG( I_FLAG );
		R.PC = RD6502(IRQ_VECTOR);
	}
	private inline function	REL_JUMP():Void
	{
		ET = R.PC;
		if ((DT & 0x80) > 0)
		{
			EA = R.PC - (~0x80 & DT);
		}
		else
		{
			EA = R.PC + DT;
		}
		R.PC = EA;
		ADD_CYCLE(1);
		CHECK_EA();
	}
	private inline function	BCC():Void
	{
		if ( !((R.P & C_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BCS():Void
	{
		if (  ((R.P & C_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BNE():Void
	{
		if ( !((R.P & Z_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BEQ():Void
	{
		if (  ((R.P & Z_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BPL():Void
	{
		if ( !((R.P & N_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BMI():Void
	{
		if (  ((R.P & N_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BVC():Void
	{
		if ( !((R.P & V_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	BVS():Void
	{
		if (  ((R.P & V_FLAG) > 0) ) REL_JUMP();
	}
	private inline function	CLC():Void
	{
		R.P &= ~C_FLAG;
	}
	private inline function	CLD():Void
	{
		R.P &= ~D_FLAG;
	}
	private inline function	CLI():Void
	{
		R.P &= ~I_FLAG;
	}
	private inline function	CLV():Void
	{
		R.P &= ~V_FLAG;
	}
	private inline function	SEC():Void
	{
		R.P |= C_FLAG;
	}
	private inline function	SED():Void
	{
		R.P |= D_FLAG;
	}
	private inline function	SEI():Void
	{
		R.P |= I_FLAG;
	}
	private inline function	ANC():Void
	{
		R.A &= DT;
		SET_ZN_FLAG( R.A );
		TST_FLAG( (R.P&N_FLAG) > 0, C_FLAG );
	}
	private inline function	ANE():Void
	{
		R.A = (R.A|0xEE)&R.X&DT;
		SET_ZN_FLAG( R.A );
	}
	private inline function	ARR():Void
	{
		DT &= R.A;
		R.A = (DT>>1)|((R.P&C_FLAG)<<7);
		SET_ZN_FLAG( R.A );
		TST_FLAG( (R.A&0x40) > 0, C_FLAG );
		TST_FLAG( ((R.A>>6)^(R.A>>5)) > 0, V_FLAG );
	}
	private inline function	ASR():Void
	{
		DT &= R.A;
		TST_FLAG( (DT&0x01) > 0, C_FLAG );
		R.A = DT>>1;
		SET_ZN_FLAG( R.A );
	}
	private inline function	DCP():Void
	{
		DT--;
		CMP_();
	}
	private inline function	DOP():Void
	{
		R.PC++;
	}
	private inline function	ISB():Void
	{
		DT++;
		SBC();
	}
	private inline function	LAS():Void
	{
		R.A = R.X = R.S = (R.S & DT);
		SET_ZN_FLAG( R.A );
	}
	private inline function	LAX():Void
	{
		R.A = DT;
		R.X = R.A;
		SET_ZN_FLAG( R.A );
	}
	private inline function	LXA():Void
	{
		R.A = R.X = ((R.A|0xEE)&DT);
		SET_ZN_FLAG( R.A );
	}
	private inline function	RLA():Void
	{
		if( (R.P & C_FLAG) > 0 ) {
			TST_FLAG( (DT&0x80) > 0, C_FLAG );
			DT = (DT<<1)|1;
		} else {
			TST_FLAG( (DT&0x80) > 0, C_FLAG );
			DT <<= 1;
		}
		R.A &= DT;
		SET_ZN_FLAG( R.A );
	}
	private inline function	RRA():Void
	{
		if( (R.P & C_FLAG) > 0 ) {
			TST_FLAG( (DT&0x01) > 0, C_FLAG );
			DT = (DT>>1)|0x80;
		} else {
			TST_FLAG( (DT&0x01) > 0, C_FLAG );
			DT >>= 1;
		}
		ADC();
	}
	private inline function	SAX():Void
	{
		DT = R.A & R.X;
	}
	private inline function	SBX():Void
	{
		WT = (R.A&R.X)-DT;
		TST_FLAG( WT < 0x100, C_FLAG );
		R.X = WT&0xFF;
		SET_ZN_FLAG( R.X );
	}
	private inline function	SHA():Void
	{
		DT = R.A & R.X & ((EA>>8)+1);
	}
	private inline function	SHS():Void
	{
		R.S = R.A & R.X;
		DT = R.S & ((EA>>8)+1);
	}
	private inline function	SHX():Void
	{
		DT = R.X & ((EA>>8)+1);
	}
	private inline function	SHY():Void
	{
		DT = R.Y & ((EA>>8)+1);
	}
	private inline function	SLO():Void
	{
		TST_FLAG( (DT&0x80) > 0, C_FLAG );
		DT <<= 1;
		R.A |= DT;
		SET_ZN_FLAG( R.A );
	}
	private inline function	SRE():Void
	{
		TST_FLAG( (DT&0x01) > 0, C_FLAG );
		DT >>= 1;
		R.A ^= DT;
		SET_ZN_FLAG( R.A );
	}
	private inline function	TOP():Void
	{
		R.PC += 2;
	}

	/********************************
	 *********** 辅助函数 ***********
	 ********************************/

	private inline function OP6502(addr:UInt):UInt
	{
		return MMU.Read(addr + MMU.CPU_BANK_OFFSET);
	}
	private inline function RD6502(addr:UInt):UInt
	{
		var value:UInt;
		if (addr < 0x2000)
		{
			value = MMU.Read((addr + MMU.CPU_BANK_OFFSET) & 0x07FF);
		}
		else
		{
			value = MMU.Read(addr + MMU.CPU_BANK_OFFSET);
		}
		// Quick bank read
		return value;
	}
	private inline function WR6502(addr:UInt, data:UInt):Void
	{
		if (addr < 0x2000)
		{
			// RAM (Mirror $0800, $1000, $1800)
			MMU.Write((addr + MMU.CPU_BANK_OFFSET) & 0x07FF, data);
		}
		else
		{
			// Others
			MMU.Write(addr + MMU.CPU_BANK_OFFSET, data);
		}
	}
	// address searh mode
	private inline function MR_IM():Void
	{
		DT = OP6502( R.PC++ );
	}
	private inline function MR_ZP():Void
	{
		EA = OP6502( R.PC++ );
		DT = ZPRD( EA );
	}
	private inline function MR_ZX():Void
	{
		DT = OP6502( R.PC++ );
		EA = (DT + R.X);
		DT = ZPRD( EA );
	}
	private inline function MR_ZY():Void
	{
		DT = OP6502( R.PC++ );
		EA = (DT + R.Y);
		DT = ZPRD( EA );
	}
	private inline function MR_AB():Void
	{
		EA = OP6502( R.PC );
		R.PC += 2;
		DT = RD6502( EA );
	}
	private inline function MR_AX():Void
	{
		ET = OP6502( R.PC );
		R.PC += 2;
		EA = ET + R.X;
		DT = RD6502( EA );
	}
	private inline function MR_AY():Void
	{
		ET = OP6502( R.PC );
		R.PC += 2;
		EA = ET + R.Y;
		DT = RD6502( EA );
	}
	private inline function MR_IX():Void
	{
		DT = OP6502( R.PC++ );
		EA = ZPRDW( DT + R.X );
		DT = RD6502( EA );
	}
	private inline function MR_IY():Void
	{
		DT = OP6502( R.PC++ );
		ET = ZPRDW( DT );
		EA = ET + R.Y;
		DT = RD6502( EA );
	}
	// EFFECTIVE ADDRESS
	private inline function EA_ZP():Void
	{
		EA = OP6502( R.PC++ );
	}
	private inline function EA_ZX():Void
	{
		DT = OP6502( R.PC++ );
		EA = (DT + R.X);
	}
	private inline function EA_ZY():Void
	{
		DT = OP6502( R.PC++ );
		EA = (DT + R.Y);
	}
	private inline function EA_AB():Void
	{
		EA = OP6502( R.PC );
		R.PC += 2;
	}
	private inline function EA_AX():Void
	{
		ET = OP6502( R.PC );
		R.PC += 2;
		EA = ET + R.X;
	}
	private inline function EA_AY():Void
	{
		ET = OP6502( R.PC );
		R.PC += 2;
		EA = ET + R.Y;
	}
	private inline function EA_IX():Void
	{
		DT = OP6502( R.PC++ );
		EA = ZPRDW( DT + R.X );
	}
	private inline function EA_IY():Void
	{
		DT = OP6502( R.PC++ );
		ET = ZPRDW( DT );
		EA = ET + R.Y;
	}
	private inline function MW_ZP():Void
	{
		ZPWR(EA, DT);
	}
	private inline function MW_EA():Void
	{
		WR6502(EA, DT);
	}

	// STACK
	private inline function PUSH(value:UInt):Void
	{
		MMU.Write(R.S--, value);
	}
	private inline function POP():UInt
	{
		return MMU.Read(++R.S);
	}

	private inline function ZPRD(addr:UInt):UInt
	{
		return OP6502(addr);
	}
	private inline function ZPRDW(addr:UInt):UInt
	{
		return OP6502(addr) + (OP6502(addr + 1) << 8);
	}
	private inline function ZPWR(addr:UInt, value:UInt):Void
	{
		WR6502(addr, value);
	}
	private inline function ADD_CYCLE(value:UInt):Void
	{
		EXEC_cycles += value;
	}
	private inline function CHECK_EA():Void
	{
		if ( (ET & 0xFF00) != (EA & 0xFF00) ) ADD_CYCLE(1);
	}
	private inline function SET_ZN_FLAG(addr:UInt):Void
	{
		R.P &= ~(Z_FLAG | N_FLAG); R.P |= GET_ZN_TABLE(addr);
	}
	private inline function GET_ZN_TABLE(addr:UInt):UInt
	{
		return MMU.Read(addr + MMU.ZN_TABLE_OFFSET);
	}
	private inline function SET_FLAG(value:UInt):Void
	{
		R.P |= value;
	}
	private inline function CLR_FLAG(value:UInt):Void
	{
		R.P &= ~value;
	}
	private inline function TST_FLAG(flag:Bool, value:UInt):Void
	{
		R.P &= ~value; if (flag) R.P |= value;
	}
	private inline function CHK_FLAG(value:UInt):UInt
	{
		return  R.P & value;
	}

	private var nes:NES;

	private var R:R6502;
	private var OpcodeMap:Vector < Void -> Void > ;
	
	private var TOTAL_cycles:Int;	// CPU周期总数
	private var DMA_cycles:Int;	// DMA周期
	private var EXEC_cycles:Int;	// 当前执行的周期

	private var WT:UInt;	// .... WORD TEMP
	private var EA:UInt;	// .... EFFECTIVE ADDRESS
	private var ET:UInt;	// .... EFFECTIVE ADDRESS TEMP
	private var DT:UInt;	// .... DATA

	// 6502 status flags
	private static inline var C_FLAG:UInt 		= 0x01;		// 1: Carry
	private static inline var Z_FLAG:UInt 		= 0x02;		// 1: Zero
	private static inline var I_FLAG:UInt 		= 0x04;		// 1: Irq disabled
	private static inline var D_FLAG:UInt 		= 0x08;		// 1: Decimal mode flag (NES unused)
	private static inline var B_FLAG:UInt 		= 0x10;		// 1: Break
	private static inline var R_FLAG:UInt 		= 0x20;		// 1: Reserved (Always 1)
	private static inline var V_FLAG:UInt 		= 0x40;		// 1: Overflow
	private static inline var N_FLAG:UInt 		= 0x80;		// 1: Negative

	// Vector
	private static inline var NMI_VECTOR:UInt 	= 0xFFFA;
	private static inline var RES_VECTOR:UInt 	= 0xFFFC;
	private static inline var IRQ_VECTOR:UInt 	= 0xFFFE;

	// Interrupt
	private static inline var NMI_FLAG:UInt 	= 0x01;
	private static inline var IRQ_FLAG:UInt 	= 0x02;

	private static inline var IRQ_FRAMEIRQ:UInt = 0x04;
	private static inline var IRQ_DPCM:UInt 	= 0x08;
	private static inline var IRQ_MAPPER:UInt 	= 0x10;
	private static inline var IRQ_MAPPER2:UInt 	= 0x20;
	private static inline var IRQ_TRIGGER:UInt 	= 0x40;
	private static inline var IRQ_TRIGGER2:UInt = 0x80;
	private inline function IRQ_MASK():Bool
	{
		return (~(NMI_FLAG | IRQ_FLAG)) > 0;
	}
}
class R6502
{
	public var PC:UInt;
	/* CPU registers     */
	public var A:UInt;
	public var P:UInt;
	public var X:UInt;
	public var Y:UInt;
	public var S:UInt;
	public var INT_pending:UInt;

	public function new()
	{
	}
}

